home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers2.zip / NTI16.ASM < prev    next >
Assembly Source File  |  1992-01-23  |  31KB  |  1,312 lines

  1. version    equ    0
  2.  
  3. ;   This program is free software; you can redistribute it and/or modify
  4. ;   it under the terms of the GNU General Public License as published by
  5. ;   the Free Software Foundation, version 1.
  6. ;
  7. ;   This program is distributed in the hope that it will be useful,
  8. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. ;   GNU General Public License for more details.
  11. ;
  12. ;   You should have received a copy of the GNU General Public License
  13. ;   along with this program; if not, write to the Free Software
  14. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  
  16.     include    defs.asm
  17.  
  18. ;        ntinet.mac
  19. ;
  20. ;  macros used for calling c routines.
  21. ;
  22. pusharg    macro    seg, off
  23.     ifnb    <seg>
  24.       push    seg
  25.     $$cnt = $$cnt+2
  26.     endif
  27.     ifnb    <off>
  28.       push    off
  29.     $$cnt = $$cnt+2
  30.     endif
  31.     endm
  32.  
  33.  
  34. ccall    macro    rtn, p1, p2, p3, p4, p5
  35. $$cnt = 0
  36.     ifnb    <p5>
  37.       pusharg    p5
  38.     endif
  39.     ifnb    <p4>
  40.       pusharg    p4
  41.     endif
  42.     ifnb    <p3>
  43.       pusharg    p3
  44.     endif
  45.     ifnb    <p2>
  46.       pusharg    p2
  47.     endif
  48.     ifnb    <p1>
  49.       pusharg    p1
  50.     endif
  51.       call    rtn
  52.     if $$cnt
  53.       add    sp,$$cnt
  54.     endif
  55.     endm
  56.  
  57. save    macro    regs
  58.       irp    arg,<regs>
  59.       push    arg
  60.       endm
  61.     endm
  62.     
  63. restore    macro    regs
  64.       irp    arg,<regs>
  65.       pop    arg
  66.       endm
  67.     endm
  68.  
  69. ;
  70.  
  71.     include    lance.inc
  72.  
  73. ;
  74. ;  GLBL.INC
  75. ;
  76. ;  global equates for lance dumb board
  77. ;
  78. pt_status    equ    0        ;read status port
  79. pt_clrclk    equ    0        ;write to clear clock interrupt
  80. pt_etaddr    equ    1        ;read ether address rom offset
  81. pt_resetl    equ    1        ;write to reset lance
  82. pt_ldata    equ    2        ;lance data port 2,3
  83. pt_laddr    equ    4        ;lance address port 4,5
  84.  
  85. st_mask        equ    0ch        ;00001100B for (is1 is0)
  86.  
  87. ;int selects
  88. irqn_10    equ    00h            ;(is0 is1) = (0 0)
  89. irqn_11    equ    04h            ;(0 1)
  90. irqn_12    equ    08h            ;(1 0)
  91. irqn_15    equ    0ch            ;(1 1)
  92.  
  93. IRQ10        equ    10
  94.  
  95. ; status port bits
  96.  
  97. NET_INT    equ    01h        ;bit for net interrupt status
  98. CLK_INT    equ    02h        ;bit for clock interrupt status
  99. IPL    equ    04h        ;ipl bit
  100. HILO    equ    08h        ;ram at 0000, or ram at 8000
  101. MINT    equ    net_int+clk_int        ;interrupt mask
  102. ADDR    equ    0F0h        ;mask for dual port segment
  103.  
  104.  
  105. DPLEN    equ    8000h        ;length of dual port ram
  106. BUFSIZE equ    1518        ;should change to GIANT + 4(CRC)
  107.  
  108. ; Packet sizes = source(6) + destination(6) + type (2) + I field. (803.2 spec)
  109. ;
  110.  
  111. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  112. ;
  113. ;Following is the list of variables that need to be adjusted if the dp
  114. ;usage is changed:
  115. ;
  116. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  117.  
  118. XAREA        equ    5F78H        ;start of transmit descriptors
  119. RAREA        equ    0018h        ;start of receive descriptors
  120.  
  121. NUMTDESC    equ    4        ;number of transmit descriptors
  122. NUMRDESC    equ    16         ;number of receive descriptors
  123.  
  124. TBAREA    equ    XAREA+(NUMTDESC*tdesclen)    ;xmit buf pool
  125. RBAREA    equ    RAREA+(NUMRDESC*rdesclen)       ;rcv buffer pool
  126.  
  127. ;our data segment is a constant distance from the es!
  128. OUROFFSET    equ    TBAREA + NUMTDESC*BUFSIZE
  129.  
  130. RLEN    equ    RLEN16            ;lance mask for rcv-descriptors
  131. TLEN    equ    TLEN4            ;lance mask for snd-descriptors
  132.  
  133. ;the total dp size reserved for lance use
  134. LANCE_SZ equ    INITBLK_SZ+ NUMRDESC*(RDESCLEN+BUFSIZE)+ NUMTDESC*(TDESCLEN+BUFSIZE)
  135.  
  136. ;the end of RAERA
  137. OUTOF_BOUND    equ     RBAREA        ;98; for wrap up checking of r-descs
  138.  
  139.  
  140. code    segment    word public
  141.     assume    cs:code, ds:code
  142.  
  143.     extrn    maskint:near
  144.     extrn    set_recv_isr: near
  145.  
  146.  
  147.     public    int_no, io_addr, base_addr
  148. int_no        db    3,0,0,0        ; interrupt number. 
  149. io_addr        dw    0338h,0        ; I/O address for card (jumpers)
  150. base_addr    dw      0d000h,0    ; base segment for board (jumper set)
  151.  
  152. int_no_name    db    "Interrupt number ",'$'
  153. io_addr_name    db    "I/O port ",'$'
  154. base_addr_name    db    "Memory address ",'$'
  155.  
  156. nosdesc_msg    db    "no send descriptor.",CR,LF,'$'
  157. chperr_msg    db    "chip doesn't want to finish init",CR,LF,'$'
  158. porterr_msg    db    "wrong port #",CR,LF,'$'
  159. hwerr_msg    db    "hardware error",CR,LF,'$'
  160. initerr_msg    db     "can't init lance chip",CR,LF,'$'
  161. good_msg    db    "Lance initialized successfully.",CR,LF,'$'
  162. reset_msg    db    "Can't reset the interface",CR,LF,'$'
  163. interr_msg    db    "IRQ# parameter wrong.",CR,LF,'$'
  164.  
  165.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  166. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  167. driver_type    db    100        ;--mz?
  168. driver_name    db    'nti',0,'$'    ;name of the driver.
  169. driver_function    db    2
  170. parameter_list    label    byte
  171.     db    1    ;major rev of packet driver
  172.     db    9    ;minor rev of packet driver
  173.     db    14    ;length of parameter list
  174.     db    EADDR_LEN    ;length of MAC-layer address
  175.     dw    GIANT    ;MTU, including MAC headers
  176.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  177.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  178.     dw    0    ;(# of successive xmits) - 1
  179. int_num    dw    0    ;Interrupt # to hook for post-EOI
  180.             ;processing, 0 == none,
  181.  
  182.     public    rcv_modes
  183. rcv_modes    dw    4        ;number of receive modes in our table.
  184.         dw    0,0,0,rcv_mode_3
  185.  
  186.  
  187.     ;begin importing data
  188.     public    UNITID, sdesc_cnt, rdesc_cnt, actsdesc, actrdesc
  189. UNITID    db    6 dup (0)        ;current ether address of the interface
  190. sdesc_cnt    dw    2        ;
  191. rdesc_cnt    dw    8
  192. actsdesc    dw    0
  193. actrdesc    dw    0
  194.  
  195.  
  196.  
  197. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  198. ; send_pkt:
  199. ;
  200. ;enter with ds:si -> packet, cx = packet length.
  201. ;exit with nc if ok, or else cy if error, dh set to error number.
  202. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  203.  
  204.     public    as_send_pkt
  205. ; The Asynchronous Transmit Packet routine.
  206. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  207. ;   interrupts possibly enabled.
  208. ; Exit with nc if ok, or else cy if error, dh set to error number.
  209. ;   es:di and interrupt enable flag preserved on exit.
  210. as_send_pkt:
  211.     ret
  212.  
  213.     public    drop_pkt
  214. ; Drop a packet from the queue.
  215. ; Enter with es:di -> iocb.
  216. drop_pkt:
  217.     assume    ds:nothing
  218.     ret
  219.  
  220.     public    xmit
  221. ; Process a transmit interrupt with the least possible latency to achieve
  222. ;   back-to-back packet transmissions.
  223. ; May only use ax and dx.
  224. xmit:
  225.     assume    ds:nothing
  226.     ret
  227.  
  228.  
  229.     public    send_pkt
  230. send_pkt:
  231.     assume    ds:nothing
  232.     push    es
  233.     call    set_dp
  234.  
  235.     push    ds
  236.     call    set_ds            ;set out ds-->cs
  237.  
  238.     mov    dx,cx            ;a copy of length
  239.  
  240.     cmp    dx,GIANT        ; Is this packet too large?
  241.     ja    send_pkt_toobig
  242.  
  243.     cmp    dx,RUNT            ; minimum length for Ether
  244.     jnb    oklen
  245.     mov    dx,RUNT            ; make sure size at least RUNT
  246. oklen:
  247.     mov    bx,[actsdesc]        ;get pointer to active snd desc
  248.     mov    cx,0            ;set up count down parameters
  249. td10:
  250.     test    es:td_stat[bx],t_own    ;have empty buffer?
  251.     jz    dox0            ;yes, then send message
  252.     loop    td10            ;otherwise, wait for it
  253.     mov    dx,offset nosdesc_msg
  254.     ccall    _dispMSG,dx
  255.     mov    dh,CANT_SEND
  256.     stc                ;error ret
  257.     pop    ds
  258.     pop    es
  259.     ret
  260.  
  261. dox0:
  262.     pop    ds
  263.     mov    cx,dx            ;get back the real length
  264.     call    fill            ;ds:si - source, es:bx - dest, cx:length
  265.     ;ax has the return code, either 0 or 0ffh
  266.  
  267.     ;is chip functioning?
  268.     cmp    ax,0ffh            ;fatal error happened last time?
  269.     je    td15            ;error!
  270.     clc                ;good ret
  271.     pop es
  272.     ret
  273. td15:
  274.     mov    dh,CANT_SEND
  275.     stc
  276.     pop    es
  277.     ret
  278.  
  279. send_pkt_toobig:
  280.     mov    dh,NO_SPACE
  281.     stc
  282.     pop    ds
  283.     pop    es
  284.     ret
  285.  
  286.     include    movemem.asm
  287.  
  288. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  289. ; fill - proc the xerror  & copy message to xmit buffer
  290. ;
  291. ; entry - es:bx points to free xmit descriptor (dest)
  292. ;      ds:si --> source buf pointer
  293. ;        cx:length of data
  294. ;
  295. ; exit  - xmit buffer (bx) filled
  296. ;      ax = 0: OK; 0ffh: fatal error happened last send
  297. ;      bx changed
  298. ;
  299. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  300.     public    fill
  301. fill:
  302.     assume    ds:nothing
  303.     push    ds                ;save theirs
  304.  
  305.     call    set_ds                ;set ours
  306.  
  307.     call    xmt_errs            ;process previous errors
  308.     cmp    ax,0
  309.     je    success
  310.     pop    ds
  311.     ret                    ;ax == ffh
  312.  
  313. success:    
  314.     ;ds:si - source, es:bx - dest, cx - length
  315.     ;simply send whatever given by the application, assuming the
  316.     ;destination address and everything has been taken care of
  317.  
  318.     pop    ds
  319.     push    cx            ;save it
  320.     mov    di,es:td_addr[bx]    ;get dest buf pointer 
  321.     call    movemem            ;ds:si --> es:di
  322.     pop    cx
  323.     
  324.     push    ds
  325.     call    set_ds
  326.     ;get the sdesc ready and pump the data out
  327.     neg    cx            ;two's compliment
  328.     or    cx,td_bmask        ;set these bits
  329.     mov    es:td_bcnt[bx],cx    ;set in length to descriptor
  330.     mov    ax,0            ;set descriptor status for lance
  331.     or    ax,t_own        ;he now owns it
  332.     or    ax,t_stp        ;start of packet
  333.     or    ax,t_enp        ;end of packet
  334.     mov    es:td_stat[bx],ax    ;give it away        
  335.     mov    ax,l_tdnd+l_inea    ;tell lance we have data
  336.     call    w_csr                ;send it
  337.  
  338.     ;all done, update the actsdesc
  339.     add    bx,tdesclen        ;point at next descriptor
  340.     dec    word ptr[sdesc_cnt]        ;dec counter
  341.     jnz    tfl                ;used all?
  342.     mov    word ptr[sdesc_cnt],NUMTDESC    ;yes start at begining    
  343.     mov    bx,XAREA
  344. tfl:
  345.     mov    [actsdesc],bx        ;set pointer
  346.  
  347.     mov    ax,0            
  348.     pop    ds
  349.     ret                ;good ret
  350.  
  351. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  352. ; xmt_errs:
  353. ;    Check at if the previous send has any errors or not.
  354. ;     entry - es:bx sdesc
  355. ;    exit  - ax:0 - ok; ffh:fatal error
  356. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  357.  
  358.     public    xmt_errs
  359. xmt_errs:
  360.     mov    ax,es:td_tdr[bx]    ;get rest of status
  361.     test    ax,t_more        ;more than one retry needed
  362.     jz    xisr2
  363.     call    count_out_err
  364.     jmp    xisr3
  365. xisr2:
  366.     test    ax,t_one        ;one retry?
  367.     jz    xisr3            ;no
  368.     call    count_out_err
  369. xisr3:
  370.     test    ax,t_lcol        ;late collision
  371.     jz    xisr4            ;no
  372.     call    count_out_err
  373. xisr4:
  374.     test    ax,t_def        ;deferred xmit?
  375.     jz    xisr5
  376.     call    count_out_err
  377. xisr5:
  378.     test    ax,t_lcar        ;loss of carrier
  379.     jz    xisr6
  380.     call    count_out_err
  381. xisr6:
  382.     test    ax,t_uflo        ;silo underflow?
  383.     jz    xisr7    
  384.     jmp    fatal_err
  385. xisr7:    
  386.     test    ax,t_buff        ;buffer error no end
  387.     jz    all_rite        ;last sent all right
  388. fatal_err:
  389.     call    count_out_err
  390.     mov    ax,0ffh            ;fatal error
  391.     ret                ;
  392.  
  393. all_rite:
  394.     mov    ax,0
  395.     ret
  396.  
  397. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  398. ;get_address:
  399. ;    We get the interface address from our internal version UNITID. 
  400. ;    set_address() could change the value of UNITID.
  401. ;
  402. ;enter with es:di -> place to put the address, cx = size of address buffer.
  403. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  404. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  405.  
  406.     public    get_address
  407. get_address:
  408.     assume    ds:code
  409.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  410.     jb    get_address_2
  411.     mov    cx,EADDR_LEN
  412.     lea    si,UNITID
  413. get_address_1:
  414.     call    movemem
  415.     mov    cx,EADDR_LEN
  416.     clc
  417.     ret
  418. get_address_2:
  419.     stc
  420.     ret
  421.     
  422. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  423. ; set_address:
  424. ;    set current ethernet address in UNITID, also change the init block
  425. ;       
  426. ;enter with ds:si -> Ethernet address, CX = length of address.
  427. ;exit with nc if okay, or cy, dh=error if any errors.
  428. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  429.  
  430.     public    set_address
  431. set_address:
  432.     assume    ds:nothing
  433.     push     ax
  434.     push    di
  435.     push    es
  436.     mov    ax,cs
  437.     mov    es,ax
  438.     
  439.     cmp    cx,EADDR_LEN
  440.     jne    set_address2
  441.  
  442.     push    si                ;save it for later use
  443.     push    cx
  444.  
  445.     mov    di,offset UNITID
  446.     call    movemem
  447.  
  448.     ;should also change the init_block
  449.     call    set_dp
  450.     mov    di,offset i_padr            
  451.     pop    cx
  452.     pop    si                ;get back the old pointer
  453.     call    movemem
  454.  
  455.     pop    es
  456.     pop    di
  457.     pop    ax
  458.     clc
  459.     ret
  460.  
  461. set_address2:
  462.     mov    dh,BAD_ADDRESS
  463.     stc
  464.     pop    es
  465.     pop    di
  466.     pop    ax
  467.     ret
  468.  
  469.  
  470.  
  471. rcv_mode_3:
  472. ;receive mode 3 is the only one we support, so we don't have to do anything.
  473.     ret
  474.  
  475.  
  476.     public    set_multicast_list
  477. set_multicast_list:
  478. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  479. ;return nc if we set all of them, or cy,dh=error if we didn't.
  480.     mov    dh,NO_MULTICAST
  481.     stc
  482.     ret
  483.  
  484.  
  485.     public    terminate
  486. terminate:
  487.     ret
  488.  
  489.     public    reset_interface
  490. reset_interface:
  491. ;reset the interface.
  492.     assume    ds:code
  493.     call    hardware        ;reset the UNITID
  494.     cmp    al,0
  495.     jne    port_err
  496.  
  497.     cli
  498.  
  499.     call    lance_init        ;init_blk, xmt, rcv
  500.     cmp    ax,0            ;init ok?
  501.     jne    lance_err
  502.     sti
  503.     clc
  504.     ret
  505.  
  506. lance_err:
  507.     mov    dx,offset initerr_msg
  508.     ccall    _dispMSG,dx
  509.     jmp    error
  510.  
  511. port_err:    
  512.     mov    dx,offset reset_msg
  513.     ccall    _dispMSG,dx
  514. error:
  515.     mov    dh,CANT_RESET
  516.     stc
  517.     ret
  518.  
  519. ;called when we want to determine what to do with a received packet.
  520. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  521.     extrn    recv_find: near
  522.  
  523. ;called after we have copied the packet into the buffer.
  524. ;enter with ds:si ->the packet, cx = length of the packet.
  525.     extrn    recv_copy: near
  526.  
  527.     extrn    count_in_err: near
  528.     extrn    count_out_err: near
  529.  
  530. ;called from the net_isr isr.  All registers have been saved, and ds=cs.
  531. ;Upon exit, the interrupt will be acknowledged.
  532. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  533. ; risr 
  534. ; receive interrupt service routine 
  535. ; exit: es,bx not changed
  536. ; registers: si,ax
  537. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  538.  
  539.     public    risr
  540. risr    proc    near
  541.     assume    ds:code
  542.     save    <es,bx>
  543.     call    set_dp            ;set es to dual port
  544. begin:
  545.     mov    si,[actrdesc]        ;active receive descriptor
  546.     mov    ax,es:rd_stat[si]    ;get descriptor status
  547.     test    ax,r_own        ;do we own it?
  548.     jnz    risr_done        ;this one is not filled
  549.  
  550.     call    dp_rcv            ;lance chip has rev'd a new packet
  551.                     ;reserve si 
  552.     ;One rint might indicate multiple recv's, check at the next one
  553.     add    si,SIZE rec_desc_ring        ;point at next descriptor
  554.     cmp    si,OUTOF_BOUND            ;RAREA+(numrxbuf-1)*(SIZE rec_desc_ring) = XAREA
  555.     jl    within
  556.     mov    si,RAREA
  557. within:
  558.     mov    [actrdesc],si            ;set active pointer
  559.     jmp    begin
  560. risr_done:
  561.     restore <bx,es>
  562.     ret
  563. risr    endp
  564.  
  565. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  566. ;  dp_rcv:
  567. ;    lance chip has one buffer filled, process it.
  568. ;    enter: es:si = actrdesc
  569. ;    exit:  actrdesc updated to next desc, si unchanged
  570. ;    registers: di,ax,bx
  571. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  572.  
  573.     public    dp_rcv
  574. dp_rcv     proc     near
  575.     push    si                ;save the old actdesc
  576.     push    es            ;gonna be changed in recv_find()
  577.  
  578.     mov    ax,es:rd_stat[si]    ;is it errored packet?
  579.     test    ax,r_err        ;
  580.     jz    noerr                 ;no err
  581.     call     rcverror        ;handle the err 
  582.     jmp    clrup
  583.  
  584. noerr:
  585.     mov     di,es:rd_addr[si]    ;received packet pointer es:di
  586.     add    di,EADDR_LEN + EADDR_LEN;stript off the two ether addresses
  587.                     ; & get to the packet type field
  588.     mov    cx,es:rd_mcnt[si]    ;everything (icl'g addresses)
  589.     and    cx,mcnt_mask        ;mask out the reserved bits
  590.  
  591.     push    ds            ;entry value saved
  592.  
  593.     push    es            ;es:di --> rcv'd data (icl'ing type)
  594.     push    di
  595.  
  596.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  597.     mov    ax, es:[di]
  598.     xchg    ah, al
  599.     cmp     ax, 1500
  600.     ja    BlueBookPacket
  601.     inc    di            ;set di to 802.2 header
  602.     inc    di
  603.     mov    dl, IEEE8023
  604. BlueBookPacket:
  605.  
  606.     call    recv_find        ;ask for buffer from application es:di
  607.     mov    ax,es            ;is this pointer null?
  608.     or    ax,di
  609.     jz    too_bad            ;yes - just free the frame.
  610.     pop    si            ;put rcv'd data in ds:si, di->si
  611.     sub    si,EADDR_LEN + EADDR_LEN;we hand everything to the client
  612.     pop    ds            ;es->ds
  613.  
  614.     push    cx
  615.     push    es            ;for recv_copy(), es:di is user buf
  616.     push    di            
  617.  
  618.     call    movemem            ;do the copy (including ether header)
  619.  
  620.     pop    si            ;di->si, es->ds
  621.     pop    ds            ;ds:si --> user buffer now
  622.     pop    cx            ;get back the length
  623.     call    recv_copy
  624.  
  625.     pop    ds            ;original ds restored
  626.     jmp    clrup
  627.  
  628. too_bad:
  629.     pop    di
  630.     pop    es
  631.     pop    ds
  632. clrup:
  633.     ;either a bad or a good packet, we're done with it now
  634.     pop    es            ;good old dp seg
  635.     pop    si
  636.     mov    es:rd_stat[si],r_own    ;desc reusable now
  637.     ret
  638. dp_rcv    endp
  639.  
  640. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  641. ; eisr
  642. ; for lance error service routine
  643. ;
  644. ; entry - bx has status
  645. ; exit  - bx unchanged, ax,cx changed
  646. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  647.  
  648.     public    eisr
  649. eisr    proc    near
  650.     test    bx,l_babl        ;transmission timeout?
  651.     jz    eisr1            ;no
  652.     call    count_out_err
  653. eisr1:
  654.     test    bx,l_cerr    
  655.     jz    eisr2            ;no
  656.     call    count_out_err
  657. eisr2:
  658.     test    bx,l_miss        ;missed packet?
  659.     jz    eisr3
  660.     call    count_out_err
  661. eisr3:
  662.     test    bx,l_merr        ;bus timeout?
  663.     jz    eisr4            ;no
  664.     call    count_out_err        ;this is a fatal error
  665. eisr4:
  666.     ret
  667. eisr    endp
  668.  
  669. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  670. ; rcverror:
  671. ;    entry    ax has rd_stat
  672. ;
  673. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  674.  
  675.     public    rcverror
  676. rcverror    proc    near
  677.  
  678.     test    ax,r_fram        ;framing error?
  679.     jz    rerr0
  680.     call     count_in_err
  681. rerr0:
  682.     test    ax,r_crc        ;crc error?
  683.     jz    rerr1
  684.     call     count_in_err
  685. rerr1:
  686.     test    ax,r_oflo          ;silo overflow?
  687.     jz    rerr2
  688.     call     count_in_err
  689. rerr2:
  690.     test    ax,r_buff        ;buffer error?
  691.     jz    rerr3
  692.     call     count_in_err
  693. rerr3:
  694.     ret
  695. rcverror    endp
  696.  
  697. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  698. ; init_csr:
  699. ;
  700. ; initialize lance registers csr1, csr2, csr3
  701. ;  entry - csr0 stop bit must have been set
  702. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  703.  
  704.     public    init_csr
  705. init_csr    proc    near
  706.     mov    al,csr1            ;set rap to csr1
  707.     call    set_rap
  708.     mov    ax,i_mode        ;init block starts at 0
  709.     call    w_csr
  710.  
  711.     mov    al,csr2            ;set rap to csr2
  712.     call    set_rap
  713.     mov    ax,0            ;init block upper 8 bits are 0
  714.     call    w_csr
  715.  
  716.     mov    al,csr3            ;set rap for csr3
  717.     call    set_rap
  718.     mov    ax,bus_master        ;bswp,acon,bcon
  719.     call    w_csr
  720.  
  721.     mov    al,csr0            ;leave rap at csr0
  722.     call    set_rap
  723.     ret
  724. init_csr    endp    
  725.  
  726. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  727. ; r_csr:
  728. ;
  729. ; read lance csr already selected into ax
  730. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  731.  
  732.     public    r_csr
  733. r_csr    proc    near
  734.     push    dx
  735.     mov    dx,io_addr        ;now data port
  736.     add    dx,pt_ldata
  737.     in    ax,dx
  738.     pop    dx
  739.     ret
  740. r_csr    endp
  741. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  742. ; r_csr0
  743. ;
  744. ; read lance csr0
  745. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  746.  
  747.     public    r_csr0
  748. r_csr0    proc    near
  749.     push    dx
  750.     mov    al,csr0            ;set rap to csr1
  751.     call    set_rap
  752.     mov    dx,io_addr        ;now data port
  753.     add    dx,pt_ldata
  754.     in    ax,dx
  755.     pop    dx
  756.     ret
  757. r_csr0    endp
  758.  
  759. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  760. ; set_initblk:  
  761. ;
  762. ; set up lance initialization block in the dual port  
  763. ;
  764. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                       ;
  765.  
  766.     public    set_initblk,si11
  767. set_initblk  proc    near
  768.     push    es
  769.     call    set_dp            ;get lance data seg
  770.  
  771.     mov    ax,run_mode        ;mode
  772.     mov    es:[i_mode],ax        ;(es = dpseg);1st word in the dp
  773.     lea    si,UNITID        ;set in physical address
  774.     mov    di,i_padr        ; from the board
  775. si11:
  776.     mov    cx,6
  777.     rep    movsb
  778. ;
  779. ;forget about the logical address filter for now --mz??
  780. ;
  781.     mov    ax,RAREA        ;set in pointer to 1ST receive desc.
  782.     mov    es:[i_rdra],ax        ;set lo addr (0-15)
  783.     mov    ah,rlen            ;set in rlen parameter & hi addr (00s)
  784.     mov    al,0
  785.     mov    es:[i_rlen],ax        ;4 rcv descriptors
  786.     mov    ax,XAREA        ;pointer to xmit descriptors
  787.     mov    es:[i_tdra],ax
  788.     mov    ah,tlen            ;set in tlen parameter 1 = 2
  789.     mov    al,0
  790.     mov     es:[i_tlen],ax
  791.     pop    es
  792.     ret
  793. set_initblk    endp
  794.  
  795. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  796. ; set_dp
  797. ;    es<-- cs:base_address
  798. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  799.  
  800.     public    set_dp
  801. set_dp:
  802.     assume    cs:code
  803.     push    ax
  804.     mov    ax,cs:[base_addr]
  805.     mov    es,ax
  806.     pop    ax
  807.     ret
  808.  
  809. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  810. ; set_ds:
  811. ;     ds<--cs
  812. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  813. set_ds:
  814.     push    ax
  815.     mov    ax,cs
  816.     mov    ds,ax
  817.     pop    ax
  818.     ret
  819.  
  820. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  821. ; set up transmit message descriptors
  822. ;
  823. ; entry - cx has number of descriptors and buffers to set up
  824. ;         bx has pointer of start of descriptors
  825. ;         di has pointer to start of buffer area
  826. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  827.  
  828.     public    su_tmd
  829. su_tmd    proc    near
  830.     push    es
  831.     call    set_dp            ;get lance data seg
  832.  
  833.     ;first set the relative parameters
  834.     mov    [sdesc_cnt],cx        ;set in count
  835.     mov    [actsdesc],bx
  836.  
  837. su_t0:
  838.     mov    es:td_addr[bx],di    ;set in pointer
  839.     mov    ax,BUFSIZE        ;total size
  840.     neg    ax            ;two's compliment
  841.     or    ax,td_bmask        ;set these bits
  842.     mov    es:td_bcnt[bx],ax    ;set in length to descriptor
  843.     mov    ax,0            ;set descriptor status for lance
  844.     or    ax,t_stp        ;start of packet
  845.     or    ax,t_enp        ;end of packet
  846.     mov    es:td_stat[bx],ax    ;give it away        
  847.     mov    es:td_tdr[bx],0
  848.     add    bx,tdesclen        ;point at next descriptor
  849.     add    di,BUFSIZE        ;and next buffer
  850.     loop    su_t0            ;do all
  851.     pop    es
  852.     ret
  853. su_tmd    endp
  854.  
  855. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  856. ; set up receive message descriptors
  857. ;
  858. ; entry - cx has number of descriptors and buffers to set up
  859. ;         bx has pointer of start of descriptors
  860. ;         di has pointer to start of buffer area
  861. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  862.  
  863.     public    su_rmd
  864. su_rmd    proc    near
  865.     push    es
  866.     call    set_dp    ;get lance data seg
  867.  
  868.     mov    [actrdesc],bx          ;pointer to active descriptor
  869.     mov    [rdesc_cnt],cx        ;descriptor count
  870. su_r0:
  871.     mov    es:rd_addr[bx],di       ;set in pointer to pointer
  872.     mov    ax,r_own        ;set up descriptor status 
  873.     mov    es:rd_stat[bx],ax
  874.     xor    ax,ax            ;zero out count
  875.     mov    es:rd_mcnt[bx],ax
  876.     mov    ax,BUFSIZE        ;set in length of buffer
  877.     neg    ax            ;must be two's compliment
  878.     or    ax,rd_mask        ;need these bits set
  879.     mov    es:rd_bcnt[bx],ax
  880.     add    bx,rdesclen        ;point at next descriptor
  881.     add    di,BUFSIZE        ;and next buffer
  882.     loop    su_r0            ;do all
  883.     
  884.     pop    es
  885.     ret
  886. su_rmd    endp
  887.  
  888. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  889. ; lance_reset:
  890. ;
  891. ;     reset lance chip; select csr0 and set the stop bit
  892. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;        
  893.  
  894.     public    lance_reset
  895. lance_reset    proc    near
  896.     mov    dx,io_addr        ;pop the reset line
  897.     add    dx,pt_resetl    
  898.     out    dx,al
  899.     mov    al,csr0            ;set lance address port to csr0
  900.     call    set_rap
  901.     mov    ax,l_stop         ;and set stop bit
  902.     call    w_csr
  903.     ret
  904. lance_reset    endp
  905.  
  906. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  907. ; w_csr:
  908. ;
  909. ; output ax to lance csr already selected
  910. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  911.  
  912.     public    w_csr
  913. w_csr    proc    near
  914.     push    dx
  915.     mov    dx,io_addr        ;now data port
  916.     add    dx,pt_ldata
  917.     out    dx,ax
  918.     pop    dx
  919.     ret    
  920. w_csr    endp
  921.  
  922. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  923. ; set_rap:
  924. ;
  925. ; set lance address port to register in al
  926. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  927.  
  928.     public    set_rap
  929. set_rap    proc    near
  930.     push    dx
  931.     mov    dx,io_addr        ;get base address
  932.     add    dx,pt_laddr                ;point at lance address port
  933.     xor    ah,ah            ;point at csr
  934.     out    dx,ax
  935.     pop    dx
  936.     ret
  937. set_rap        endp
  938.  
  939. ; hardwre() and lance_init() are TSR just for the 
  940. ; support of reset_interface();
  941.  
  942. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  943. ; hardware: 
  944. ;    verify the port #;
  945. ;    set ethernet addr in _UNITID
  946. ;
  947. ; exit:
  948. ;    [_UNITID] = board ethernet address
  949. ;       al = 0 (ok)
  950. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  951.  
  952.     public    hardware
  953. hardware    proc    near
  954.     ;verify the port #
  955.     mov    dx,io_addr
  956.     call    chkaddr
  957.     cmp    al,0            ;ok?
  958.     jz    hw1            ;yes, use #1
  959.     mov    ax,offset porterr_msg
  960.     ccall    _dispMSG,ax
  961.     jmp    hw_error
  962.  
  963. hw1:
  964.     ;ok, now zero the ram out so that we can use it
  965.     call    set_dp
  966.     call     zeroram
  967.  
  968.     ;get ether address
  969.     mov    cx,6            ;get the ethernet address
  970.     add    dx,pt_etaddr
  971.     mov    bx,offset UNITID    ;to here
  972. hw3:
  973.     in    al,dx
  974.     mov    byte ptr[bx],al
  975.     inc    bx
  976.     loop    hw3
  977.  
  978.     ;validate int_no (only support 10,11,12,15)
  979.     
  980.     mov    bl,IRQ10        ;assume it's irq10
  981.     mov    dx,io_addr        ;port base
  982.     add     dx,pt_status        ;status port
  983.     in    al,dx            ;get status
  984.     and    al,st_mask        ;get the 2 bits
  985.     cmp    al,irqn_10        ;(IS0 IS1)=(0 0) selects irq10
  986.     je    alset
  987.     inc    bl            ;try irq11
  988.     cmp    al,irqn_11
  989.     je    alset
  990.     inc    bl            ;try irq12
  991.     cmp    al,irqn_12
  992.     je    alset
  993.     mov    bl,15            ;try irq15
  994.     cmp    al,irqn_15
  995.     jne    hw_error
  996.  
  997. alset:
  998.     ;did we get the right int_no in bl?
  999.     cmp    bl,int_no
  1000.         jmp     ok                      ; #### temp patch, BKC
  1001. ;    je    ok
  1002.     ;otherwise, error
  1003.     mov    ax,offset interr_msg
  1004.     ccall    _dispMSG,ax
  1005. hw_error:
  1006.     mov    al,0ffh
  1007.     ret
  1008. ok:
  1009.     mov    al,0            ;good return code
  1010.     ret
  1011. hardware    endp
  1012.  
  1013. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1014. ; chkaddr: check if we are using the right i/o port
  1015. ;          this is done by reading the port status and comparing
  1016. ;       with cs - 800h
  1017. ;
  1018. ; entry:     io_addr == i/o port #
  1019. ; exit:     ah -- dual port segment
  1020. ;        al -- 00h (succ) or ffh (error)
  1021. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1022.  
  1023.     public    chkaddr
  1024. chkaddr    proc    near
  1025.     push    dx
  1026.  
  1027.     mov    dx,io_addr
  1028.     in    al,dx            ;read in status byte
  1029.     and    al,addr            ;get dp seg, addr = 0f0h
  1030.     mov    ah,al            ;save
  1031.  
  1032.     mov    dx,base_addr
  1033.     and    dh,addr
  1034.     cmp    al,dh
  1035.     je    chk2
  1036.     mov    al,0ffh            ;error
  1037.     pop    dx
  1038.     ret
  1039. chk2:
  1040.     mov    al,0            ;ok
  1041.     pop    dx
  1042.     ret
  1043. chkaddr    endp
  1044.  
  1045. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1046. ; zeroram - zero dual port ram
  1047. ;    seg in [dpseg]
  1048. ;    registers: di,cx,al
  1049. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1050.  
  1051.     public    zeroram
  1052. zeroram    proc    near
  1053.     cld                ;auto increment
  1054. zram1:    
  1055.     mov    di,0            ;start at 0;dpseg:di
  1056.     mov    cx,dplen        ;dual port length
  1057.     mov    al,0            ;data to go
  1058.     rep    stosb            ;zero em all
  1059.     ret
  1060. zeroram    endp
  1061.  
  1062. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1063. ; lance_init:
  1064. ;
  1065. ; init lance chip; first setup init_blk, r & s descriptors in dp
  1066. ;           then set the chip to go.
  1067. ;    exit: ax = 1: error; 0 OK. 
  1068. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1069.  
  1070.     public    lance_init, il0, il1
  1071. lance_init    proc    near
  1072.     call    set_initblk        ;set up lance initialization block
  1073.  
  1074.     ;set up transmit descriptors & buffers
  1075.     mov    cx,NUMTDESC        ;get no. of transmit blocks to build
  1076.     mov    bx,XAREA        ;point at descriptor memory pool
  1077.     mov    di,TBAREA        ;and buffer pool
  1078.     call    su_tmd            ;set up transmit descriptors
  1079.  
  1080.     ;set up receive descriptors & buffers
  1081.     mov    cx,NUMRDESC        ;set up receive descriptors
  1082.     mov    bx,RAREA        ;descriptor area
  1083.     mov    di,RBAREA        ;buffer area
  1084.     call    su_rmd            ;set up receive descriptors
  1085.  
  1086.     call    lance_reset        ;ensure reset
  1087.     call    init_csr        ;initialize lance registers
  1088.                     ;also set rap to csr0 with stop set
  1089.     ;now start the lance initialization action
  1090.     CLI
  1091.     mov    ax,l_init+l_strt    ;write init & start to csr0
  1092.     call    w_csr
  1093.  
  1094.     ;rap = csr0 now, let's check at csr0
  1095.        mov    cx,0
  1096.     dec    cx
  1097. il0:
  1098.     call    r_csr            ;get lance status register
  1099.     test    ax,l_idon        ;init done set?
  1100.     jnz    il1
  1101.     loop    il0
  1102.     ;sth wrong with the chip, can't init
  1103.     mov    ax,offset chperr_msg
  1104.     ccall    _dispMSG,ax
  1105.     mov    ax,1            ;error return
  1106.     ret
  1107. il1:
  1108.     mov    ax,l_idon+l_inea    ;this drives /intr pin to low
  1109.     call    w_csr            ;enable network ints
  1110.     STI
  1111.     mov    ax,0            ;good return
  1112.     ret
  1113. lance_init    endp
  1114.  
  1115. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1116. ;  tickscreen
  1117. ;
  1118. ;  For debug this routine can be called to tick over the screen at the 
  1119. ;  specified location.
  1120. ;
  1121. ;    c callable:    tickscreen(loc);
  1122. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1123.  
  1124.     public    _tickscreen
  1125. _tickscreen    proc near
  1126.     push    bp
  1127.     mov    bp,sp
  1128.     save    <ax,bx,ds>
  1129.     mov    bx,04[bp]        ;get screen position
  1130.     add    bx,bx            ;*2
  1131. IFDEF COLOR
  1132.     mov    ax,0b800h
  1133. ELSE
  1134.     mov    ax,0b000h
  1135. ENDIF
  1136.     mov    ds,ax
  1137.     inc    byte ptr [bx]            ;tick it
  1138.     restore    <ds,bx,ax>
  1139.     pop    bp
  1140.     ret
  1141. _tickscreen    endp
  1142.  
  1143. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1144. ; _dispMSG:
  1145. ;    c call: dispMSG(&msg);
  1146. ;    put the '$' terminated message to screen
  1147. ;    entry: dx - point to the message
  1148. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1149.  
  1150.     public    _dispMSG
  1151. _dispMSG proc near
  1152.     push    bp
  1153.     mov    bp,sp
  1154.     push    dx
  1155.     mov    dx,4[bp]
  1156.  
  1157.     push    ax
  1158.     mov    ah,9
  1159.     int    21h
  1160.     pop    ax
  1161.  
  1162.     pop    dx
  1163.     pop    bp
  1164.     ret
  1165. _dispMSG endp
  1166.  
  1167.  
  1168.     public    recv
  1169. recv:
  1170. ;called from the recv isr.  All registers have been saved, and ds=cs.
  1171. ;Upon exit, the interrupt will be acknowledged.
  1172.     assume    ds:code
  1173.  
  1174. recv_0:
  1175.     mov    dx,io_addr        ;get the iobase
  1176.     add    dx,pt_status        ;the read status port
  1177.     in    al,dx            ;get board status
  1178.  
  1179.     test    al,clk_int        ;look for clock interrupt
  1180.     jz    ni10            ;no clock int
  1181.     mov    dx,base_addr
  1182.     add    dx,pt_clrclk        ;reset the ckock
  1183.     out     dx,al
  1184. ni10:
  1185.     test    al,net_int        ;network int bit cleared?
  1186.     jnz    nisr5            ;look for 0 here, set means none
  1187.  
  1188.     call    r_csr            ;get lance status register -- in ax
  1189.     mov    bx,ax
  1190.     and    ax,l_mask         ;clear out ints and mask any more
  1191.     call    w_csr
  1192.  
  1193.     test    bx,l_err        ;check for errors first
  1194.     jz    nisr2            ;no error
  1195.     call    eisr
  1196. nisr2:
  1197.     test    bx,l_rint        ;test for receive active
  1198.     jz    nisr6            ;no r_int
  1199.     call    risr
  1200. nisr6:
  1201.     mov     ax,l_inea        ;re-enable the int
  1202.     call    w_csr
  1203.     jmp    recv_0            ;check again for ints
  1204. nisr5:
  1205.     ret
  1206.  
  1207.  
  1208.     public    recv_exiting
  1209. recv_exiting:
  1210. ;called from the recv isr after interrupts have been acknowledged.
  1211. ;Only ds and ax have been saved.
  1212.     assume    ds:nothing
  1213.     ret
  1214.  
  1215.  
  1216. ;any code after this will not be kept after initialization.
  1217. end_resident    label    byte
  1218.  
  1219.  
  1220.     public    usage_msg
  1221. usage_msg    db    "usage: nti16 [-n] [-d] [-w] <packet_int_no> <irq_no> <port_no> <base_addr>",CR,LF,'$'
  1222.  
  1223.     public    copyright_msg
  1224. copyright_msg    db    "Packet driver for nti network device, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  1225.         db    "Copyright 1990, Michael Zheng",CR,LF,'$'
  1226.  
  1227.  
  1228. ;enter with si -> argument string, di -> wword to store.
  1229. ;if there is no number, don't change the number.
  1230.     extrn    get_number: near
  1231.  
  1232. ;enter with dx -> name of word, di -> dword to print.
  1233.     extrn    print_number: near
  1234.  
  1235.     public    parse_args
  1236. parse_args:
  1237.     mov    di,offset int_no
  1238.     call    get_number
  1239.     mov    di,offset io_addr
  1240.     call    get_number
  1241.     mov    di,offset base_addr
  1242.     call    get_number
  1243.     ret
  1244.  
  1245. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1246. ; etopen:
  1247. ;    initialize the interface in order to function
  1248. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1249.  
  1250.     public    etopen
  1251. etopen:
  1252.  
  1253.  
  1254.     call     hardware        ;decide port #; _UNITID; zeroram
  1255.                     ;and 16-bit board specific:
  1256.                     ;decide the int_no validity --mz!!
  1257.     cmp    al,0
  1258.     jz    beg0            ;ok
  1259.     mov    ax,offset hwerr_msg    ;error return
  1260.     ccall    _dispMSG,ax
  1261.     mov    ax, 4c00H
  1262.     int    21h            ;terminate it
  1263. beg0:
  1264.  
  1265.     mov    al,int_no
  1266.     call    maskint
  1267.     call    lance_init        ;init the lance chip
  1268.     cmp    ax,1            ;init error?
  1269.     jne    good            ;ok
  1270.  
  1271.     mov    ax,offset initerr_msg    ;can't init message
  1272.     ccall    _dispMSG,ax
  1273.     stc    
  1274.     ret
  1275.  
  1276. good:
  1277.     call    set_recv_isr
  1278.  
  1279.     mov    al, int_no        ; Get board's interrupt vector
  1280.     add    al, 8
  1281.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1282.     jb    set_int_num        ; No.
  1283.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1284. set_int_num:
  1285.     xor    ah, ah            ; Clear high byte
  1286.     mov    int_num, ax        ; Set parameter_list int num.
  1287.  
  1288.     mov    ax,offset good_msg
  1289.     ccall    _dispMSG,ax
  1290.  
  1291.     mov    dx,offset end_resident    ;in paragraphs
  1292.     clc
  1293.     ret
  1294.  
  1295.     public    print_parameters
  1296. print_parameters:
  1297. ;echo our command-line parameters
  1298.     mov    di,offset int_no
  1299.     mov    bx,offset int_no_name
  1300.     call    get_number
  1301.     mov    di,offset io_addr
  1302.     mov    bx,offset io_addr_name
  1303.     call    get_number
  1304.     mov    di,offset base_addr
  1305.     mov    bx,offset base_addr_name
  1306.     call    get_number
  1307.     ret
  1308.  
  1309. code    ends
  1310.  
  1311.     end
  1312.